/* Filename:    list.c
 * Author:      John Van Drasek
 * Date:        15 October 2006
 * Description: Source file for list functionality
 */


//////////////
// Includes //
//////////////

// User defined includes
#include "list.h"


//////////////////////////
// Function definitions //
//////////////////////////

/* printPktList
*
*  Description: Print a pktList.
*
*  Input: struct pktList* pList - A pktList pointer of the pktList to be printed.
*  Output: NA
*/
void PrintPktList(struct pktList* pList)
{
	struct pktList* curPktList = pList;
	struct pktNode* curPktNode = pList->_head;
	int i;

	if(curPktList->_size == 0)
	{
		printf("list is empty\n");
	}
	else
	{
		for(i = 0;i < curPktList->_size;++i)
		{
			printf("pkt[%d]._checksum = %d\n",i,((struct pkt*)curPktNode->_data)->_checksum);
			printf("pkt[%d]._id = %d\n",i,((struct pkt*)curPktNode->_data)->_id);
			printf("pkt[%d]._command = %s\n",i,((struct pkt*)curPktNode->_data)->_command);
			printf("pkt[%d]._client.sin_family = %d\n",i,((struct pkt*)curPktNode->_data)->_client.sin_family);
			printf("pkt[%d]._client.sin_addr= %s\n",i,inet_ntoa(((struct pkt*)curPktNode->_data)->_client.sin_addr));
			printf("pkt[%d]._client.sin_port= %d\n",i,((struct pkt*)curPktNode->_data)->_client.sin_port&0xffff);
			printf("pkt[%d]._client_name = %s\n",i,((struct pkt*)curPktNode->_data)->_client_name);
			printf("pkt[%d]._client_password = %s\n",i,((struct pkt*)curPktNode->_data)->_client_password);
			printf("pkt[%d]._msgbuf = %s\n",i,((struct pkt*)curPktNode->_data)->_msgbuf);
			printf("pkt[%d]._ackvar = %c\n",i,((struct pkt*)curPktNode->_data)->_ackvar);
			if(curPktNode->_next != 0)
			{
				curPktNode = curPktNode->_next;
			}
		}
	}
}

/* printPktList
*
*  Description: Print a pktList.
*
*  Input: struct pktList* pList - A pktList pointer of the pktList to be printed.
*  Output: NA
*/
void PrintUsersOnline(struct pktList* pList)
{
	struct pktList* curPktList = pList;
	struct pktNode* curPktNode = pList->_head;
	int i;

	if(curPktList->_size == 0)
	{
		printf("list is empty\n");
	}
	else
	{
		for(i = 0;i < curPktList->_size;++i)
		{
			//printf("pkt[%d]._checksum = %d\n",i,((struct pkt*)curPktNode->_data)->_checksum);
			//printf("pkt[%d]._id = %d\n",i,((struct pkt*)curPktNode->_data)->_id);
			//printf("pkt[%d]._command = %s\n",i,((struct pkt*)curPktNode->_data)->_command);
			//printf("pkt[%d]._client.sin_family = %d\n",i,((struct pkt*)curPktNode->_data)->_client.sin_family);
			printf("pkt[%d]._client.sin_addr= %s\n",i,inet_ntoa(((struct pkt*)curPktNode->_data)->_client.sin_addr));
			//printf("pkt[%d]._client.sin_port= %d\n",i,((struct pkt*)curPktNode->_data)->_client.sin_port&0xffff);
			printf("pkt[%d]._client_name = %s\n",i,((struct pkt*)curPktNode->_data)->_client_name);
			//printf("pkt[%d]._client_password = %s\n",i,((struct pkt*)curPktNode->_data)->_client_password);
			//printf("pkt[%d]._msgbuf = %s\n",i,((struct pkt*)curPktNode->_data)->_msgbuf);
			//printf("pkt[%d]._ackvar = %c\n",i,((struct pkt*)curPktNode->_data)->_ackvar);
			if(curPktNode->_next != 0)
			{
				curPktNode = curPktNode->_next;
			}
		}
	}
}

///* printPkt
// *
// *  Description: Print a pkt.
// *
// *  Input: struct pkt* ppPkt - A pkt pointer of the pkt to be printed.
// *  Output: NA
// */
//void printPkt(struct pkt* ppPkt){
//
//  printf("ppPkt->_checksum = %d\n",ppPkt->_checksum);
//  printf("ppPkt->_id = %d\n",ppPkt->_id);
//  printf("ppPkt->_command = %s\n",ppPkt->_command);
//  printf("ppPkt->_client.sin_family = %d\n",ppPkt->_client.sin_family);
//  printf("ppPkt->_client.sin_addr = %s\n",inet_ntoa(ppPkt->_client.sin_addr));
//  printf("ppPkt->_client.sin_port = %d\n",ppPkt->_client.sin_port&0xffff);
//  printf("ppPkt->_client_name = %s\n",ppPkt->_client_name);
//  printf("ppPkt->_client_password = %s\n",ppPkt->_client_password);
//  printf("ppPkt->_msgbuf = %s\n",ppPkt->_msgbuf);
//  printf("ppPkt->_ackvar = %c\n",ppPkt->_ackvar);
//}


/* getPktListItemByAddress
*
*  Description: Get a pkt from the pktList with the specified id.
*
*  Input: struct pktList* pList - The pktList to search.
*  Input: struct sockaddr_in* cpClient - 
*  Input: char* cpCName - A char pointer containing the user name
*  Input: char* cpCPassword - A char pointer containing user password
*  Input: char* cpMsgbuf - A char pointer containing some text data
*  Input: int cpCount - A total number of pkts being sent
*  Output: struct pkt* - The pkt pointer of the pkt retrieved or 0 if not found.
*/
struct pkt* GetPktListItemByAddress(struct pktList* pList, char* inIpAddress)
{

	struct pktNode* curPktNode = pList->_head;
	while(curPktNode)
	{
		if(  strcmp((inet_ntoa((((struct pkt*)curPktNode->_data)->_client.sin_addr))),inIpAddress) == 0 )
		{
			return ((struct pkt*)(curPktNode->_data));
		}
		if(curPktNode->_next)
		{
			curPktNode = curPktNode->_next;
		}
		else
		{
			return 0;
		}
	}
	return 0;
}


/* setPktListBack
*
*  Description: Add a pkt to the end of a pktList.
*
*  Input: struct pktList* pList - A pktList pointer to the pktList to
*          add the pkt to.
*  Input: struct pkt* p - A pkt pointer to the pkt to be added to the pktList.
*  Output: int ret - Returns 1 if success and 0 if failed.
*/
int SetPktListBack(struct pktList* pList, struct pkt* p)
{
	int ret = 0;
	struct pktList* curPktList = pList;
	struct pktNode* curPktNode = pList->_head;

	struct pktNode* newPktNode;
	newPktNode = new struct pktNode;

	newPktNode->_data = (int)p;
	newPktNode->_next = 0; 

	if (curPktNode)
	{
		while (curPktNode->_next)
		{
			curPktNode= curPktNode->_next;
		}
		curPktNode->_next = newPktNode;
		//printf("found end of list and added pkt.\n");
		++(curPktList->_size);
		ret = 1;
	}
	else
	{
		curPktList->_head = newPktNode;
		//printf("added pkt to first element in list\n");
		++(curPktList->_size);
		ret = 1;
	}

	if(ret == 0)
	{
		printf("pkt wasn't added to list!\n");
	}

	return ret;
}

//
///* createPkt
// *
// *  Description: Create a new pkt and return a pointer to it.
// *
// *  Input: int cpId - An id number the new pkt is to be assigned to for network code
// *          to determine if the incoming pkt is out of order.
// *  Input: char* cpCommand - A text command used to run specific functions on the server
// *  Input: struct sockaddr_in* cpClient - A socket address structure containing
// *          ip address and port number.
// *  Input: char* cpCName - A char pointer containing the user name
// *  Input: char* cpCPassword - A char pointer containing user password
// *  Input: char* cpMsgbuf - A char pointer containing some text data
// *  Input: int cpCount - A total number of pkts being sent
// *  Output: struct pkt* - The pkt pointer of the newly created pkt is returned.
// */
//struct pkt* createPkt(int cpId, char* cpCommand, struct sockaddr_in* cpClient, char* cpCName, char* cpCPassword, char* cpMsgbuf, char cpAckvar)
//{
//  struct pkt* newPkt;
//  newPkt = new struct pkt;
//
//  memset((char*)newPkt,0,sizeof(struct pkt));
//
//  newPkt->_checksum = 0;
//  newPkt->_id = cpId;
//  strncpy(newPkt->_command,cpCommand,strlen(cpCommand));
//  newPkt->_client.sin_family = cpClient->sin_family;
//  newPkt->_client.sin_addr = cpClient->sin_addr;
//  newPkt->_client.sin_port = cpClient->sin_port&0xffff; 
//  strncpy(newPkt->_client_name,cpCName,strlen(cpCName));
//  strncpy(newPkt->_client_password,cpCPassword,strlen(cpCPassword));
//  strncpy(newPkt->_msgbuf,cpMsgbuf,strlen(cpMsgbuf));
//  newPkt->_ackvar = cpAckvar;
//
//  return newPkt;
//}


/* removePktByAddress
*
*  Description: Remove a pkt from a pktList.
*
*  Input: struct pktList* pktList - A pkt pointer of the pkt to be removed.
*  Input: char* inAddress- The IP Address of the pkt to be removed.
*  Output: int ret - Returns 1 if success and 0 if failed to remove pkt from pktList
*/
int RemovePktByAddress(struct pktList* pktList, char* inAddr)
{
	int ret = 0;
	bool done = false;
	struct pktList* curPktList;
	curPktList = pktList;

	// Create a local variable for the incoming address
	//  If the incoming address is used, instead, the first
	//  strcmp will change the value in the sin_addr struct
	//  resulting in the first item in the list always being
	//  matched.
	char inAddress[ADDRESSSIZE];
	memset(inAddress,0,ADDRESSSIZE);
	strncpy(inAddress,inAddr,strlen(inAddr));

	struct pktNode* curPktNode;
	curPktNode = curPktList->_head;

	// Check to see if it is the first item in the list
	if(curPktNode)
	{
		if((strcmp(inet_ntoa(((struct pkt*)curPktNode->_data)->_client.sin_addr),inAddress) == 0))
		{
			// remove pkt
			delete ((struct pkt*)curPktNode->_data);

			if(curPktNode->_next)
			{
				curPktList->_head = curPktNode->_next;
			}
			else
			{
				// Reset the pointer to 0 if there are no more items
				//  in list.
				curPktList->_head = 0;
			}
			// delete pktNode
			delete (curPktNode);

			curPktList->_size--;
			ret = 1;
			done = true;
		}
		while(!done)
		{
			if(curPktNode->_next)
			{
				if((strcmp(inet_ntoa(((struct pkt*)(curPktNode->_next->_data))->_client.sin_addr),inAddress) == 0))
				{
					// remove pkt
					delete ((struct pkt*)(curPktNode->_next->_data));

					if(curPktNode->_next->_next)
					{
						curPktNode->_next = curPktNode->_next->_next;
					}
					else
					{
						// Reset the pointer to 0 if there are no more items
						//  in list.
						delete (curPktNode->_next);
						curPktNode->_next = 0;
					}
					curPktList->_size--;
					ret = 1;
					done = true;
				}
				// Move to the next pktNode
				curPktNode = curPktNode->_next;
			}
			else
			{
				// The specified address isn't in the list
				ret = 0;
				done = true;
			}
		}
	}
	else
	{
		// The list is empty
		ret = 0;
	}

	return ret;
}


///* copyPkt
// *
// *  Description: Create a new pkt and copy the incoming pkt contents into it.
// *
// *  Input: struct pkt* inPkt - A pkt pointer of the source pkt to be copied
// *  Output: struct pkt* - The pkt pointer of the newly created pkt is returned.
// */
//struct pkt* copyPkt(struct pkt* inPkt){
//
//  struct pkt* newPkt;
//  newPkt = new struct pkt;
//
//  memset((char*)newPkt,0,sizeof(struct pkt));
//
//  newPkt->_checksum = inPkt->_checksum;
//  newPkt->_id = inPkt->_id;
//  strncpy(newPkt->_command,inPkt->_command,strlen(inPkt->_command));
//  newPkt->_client.sin_family = inPkt->_client.sin_family;
//  newPkt->_client.sin_addr = inPkt->_client.sin_addr;
//  newPkt->_client.sin_port = inPkt->_client.sin_port&0xffff; 
//  strncpy(newPkt->_client_name,inPkt->_client_name,strlen(inPkt->_client_name));
//  strncpy(newPkt->_client_password,inPkt->_client_password,strlen(inPkt->_client_password));
//  strncpy(newPkt->_msgbuf,inPkt->_msgbuf,strlen(inPkt->_msgbuf));
//  newPkt->_ackvar = inPkt->_ackvar;
//
//  return newPkt;
//}
